package net.takela.push.service;

import jakarta.annotation.PostConstruct;
import net.takela.common.spring.exception.DataException;
import net.takela.common.spring.http.HttpResponse;
import net.takela.common.utils.DateUtils;
import net.takela.common.utils.IntegerUtils;
import net.takela.dict.service.SysConfService;
import net.takela.push.dao.PushMsgTplDao;
import net.takela.push.model.*;
import net.takela.push.service.sp.ServiceProvider;
import net.takela.push.dao.PushRecordDao;
import net.takela.push.dao.PushAppDao;
import net.takela.push.service.sp.impl.SendCloudServiceProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by baboy on 25/07/2017.
 */
@Service
public class PushRecordService {
    private final Logger logger = LoggerFactory.getLogger(PushRecordService.class);
    @Autowired
    private PushRecordDao pushRecordDao;
    @Autowired
    private PushAppDao pushAppDao;
    @Autowired
    private PushMsgTplDao pushMsgTplDao;
    @Autowired
    private SysConfService sysConfService;

    private Map<String, ServiceProvider> servicePool = new HashMap<String, ServiceProvider>();
    @Autowired
    protected ThreadPoolTaskExecutor taskExecutor;

    @PostConstruct
    public void init(){
        reset();
    }
    public void reset(){
        List<PushApp> apps = pushAppDao.getAllApps();
        for(PushApp app : apps){
            if (PushApp.APP_SP_SC_SMS.equals(app.getCode())){
                ServiceProvider sp = new SendCloudServiceProvider();
                sp.setPushApp(app);
                MsgTplSearchArg searchArg = new MsgTplSearchArg();
                searchArg.setAid(app.getId());
                List<PushMsgTpl> msgTpls = pushMsgTplDao.searchMsgTpls(searchArg);
                sp.setMsgTpls(msgTpls);
                servicePool.put(app.getType(), sp);
            }
        }
    }

    
    public boolean addPushRecord(PushRecord record) {
        boolean ret = pushRecordDao.addPushRecord(record) > 0;
        return ret;
    }

    
    public boolean updatePushRecord(PushRecord record) {
        boolean ret = pushRecordDao.updatePushRecord(record)>0;
        return ret;
    }
    
    public List<PushRecord> getPushRecords(PushRecordSearchArgs args){
        List<PushRecord> records = pushRecordDao.getPushRecords(args);
        return records;
    }


    public void addRecord(PushApp app, PushMsgTpl msgTpl, Map data, String to, String ip, String channel, boolean status, String errorMsg){
        PushRecord record = new PushRecord();
        record.setMsgType(app.getType());
        record.setAppId(app.getId());
        record.setMsgId(msgTpl.getMsgId());
        record.setChannel(channel);
        record.setTo(to);
        record.setData(data);
        record.setIp(ip);
        record.setErrorMsg(errorMsg);
        record.setStatus(status ? PushRecord.PUSH_STATUS_SUCCESS : PushRecord.PUSH_STATUS_ERROR);
        pushRecordDao.addPushRecord(record);
    }
    public boolean check(String msgType, String to,int msgId ,String channel, String ip){
        Map m =  sysConfService.getMapValue(msgType + "-policy");
        if (m == null){
            return true;
        }
        Map dayConf = (Map)m.get("day");
//        1、每个电话总发送量（不同模板） numPerMobile
//        2、每个客户ip总发送量（不同模板） numPerIp
//        3、每个模板发送量 numPerTpl
//        4、所有模板总发送量 totalOfTpl

        //检查渠道来源
        Map appConfs = (Map)dayConf.get("app");
        Map appConf = null;
        //查看渠道配置
        if (appConfs.containsKey(channel)){
            appConf = (Map)appConfs.get(channel);
        }
        //没有渠道配置就查看默认配置
        Map<String,Object> defConf = (Map<String,Object>)appConfs.get("default");
        if (appConf == null){
            appConf = defConf;
        }
        for (String key : defConf.keySet()){
            if (!appConf.containsKey(key)){
                appConf.put(key, defConf.get(key));
            }
        }
        //1、每个电话总发送量（不同模板） numPerMobile

        int numPerMobile = 0;
        if (appConf.containsKey("numPerMobile")){
            Integer.parseInt(appConf.get("numPerMobile").toString());
        }

        PushRecordSearchArgs args = new PushRecordSearchArgs();
        args.setChannel(channel);
        args.setMsgType(msgType);
        args.setMinCreateTime(DateUtils.getBeginTimeOfDay(new Date()));
        args.setMaxCreateTime(DateUtils.getEndTimeOfDay(new Date()));
        args.setTo(to);
        int n = pushRecordDao.getRecordCount(args);
        if (n >= numPerMobile){
            logger.info("|check|numPerMobile:"+n+">="+numPerMobile);
            return false;
        }

        //2、每个客户ip总发送量（不同模板） numPerIp
        int numPerIp = IntegerUtils.parseInt(appConf.get("numPerIp"));
        args.setTo(null);
        args.setAppId(null);
        args.setIp(ip);
        n = pushRecordDao.getRecordCount(args);
        if (n >= numPerIp){
            logger.info("|check|numPerIp:"+n+">="+numPerIp);
            return false;
        }
        //3、每个模板发送量 numPerTpl
        int numPerTpl = IntegerUtils.parseInt(appConf.get("numPerTpl"));
        args.setIp(null);
        args.setMsgId(msgId);
        n = pushRecordDao.getRecordCount(args);
        if (n >= numPerTpl){
            logger.info("|check|numPerTpl:"+n+">="+numPerTpl);
            return false;
        }
        //4、所有模板总发送量 totalOfTpl
        int totalOfTpl = IntegerUtils.parseInt(appConf.get("totalOfTpl"));
        args.setMsgId(null);
        n = pushRecordDao.getRecordCount(args);
        if (n >= totalOfTpl){
            logger.info("|check|totalOfTpl:"+n+">="+totalOfTpl);
            return false;
        }
        return true;
    }
    public HttpResponse push(String msgType, PushRecordSendArgs args){

        final ServiceProvider sp = servicePool.get(msgType);
        PushApp app = sp.getPushApp();
        PushMsgTpl msgTpl = sp.getMsgTpl(args.getMsgCode());
        Map data = args.getData();
        String to = null;
        if ( msgType.equalsIgnoreCase(PushApp.APP_TYPE_SMS) ){
            to = (String)data.get("mobile");
        }else{
            to =  (String)data.get("openId");
        }

        //校验
        boolean isValid = check(sp.getPushApp().getType(), to, msgTpl.getId(), args.getChannel(), args.getIp());
        if (!isValid){
            throw new DataException("auth.request.limit.exceed");
        }
        final String dest = to;
        taskExecutor.execute(new Runnable() {
            
            public void run() {
                HttpResponse ret = sp.send(args.getMsgCode(), data, args.getIp());
                addRecord(app, msgTpl, data, dest, args.getChannel(), args.getIp(), ret.isSuccess(),ret.getMessage());
            }
        });

        return HttpResponse.success();
    }

    
    public HttpResponse push(PushRecordSendArgs args) {
        String []a = args.getMsgType().split(",");
        for (int i = 0; i< a.length; i++){


            HttpResponse r = push(a[i], args);
            if (!r.isSuccess()){
                return r;
            }
            break;
        }
        return  HttpResponse.success();

    }
}
